﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zj.HttpCodeDemo.Repository.Models;
using System.Data.Entity;
using Zj.HttpCodeDemo.Domain.Entities;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.SqlServer;
using System.Diagnostics;

namespace Zj.HttpCodeDemo.ConsoleApp.Samples
{
    public class CodeFirstSample
    {
        public static void Sample()
        {
            using (var ctx = new TodoDbContext())
            {
                //ListSample(ctx);
                //StateSample(ctx);

                //var tag = ctx.Tag.First();
                //tag.Name = "悟空啊悟空";
                //tag.Order = 100;
                //PropertyModifiedSample(ctx, tag, "Name", "Order");

                //ExpressionConditionQuerySample(ctx);
                BulkInsertSample(ctx);
                //ctx.User.Add(new User() {  Pwd="p@ssw0rd", UserName="ZhangJian"});
                //ctx.SaveChanges();
            }
        }


        /// <summary>
        /// Expression condition query samples.
        /// </summary>
        private static void ExpressionConditionQuerySample(TodoDbContext ctx)
        {
            //var order = "90";
            //var tags = ctx.Tag.Where(t => t.Order > Convert.ToInt32(order))
            //    .ToList();//Bug.
            //var tags_ = ctx.Tag.Where(t => t.Order >int.Parse(order))
            //    .ToList();//Bug.
            //var diff=SqlFunctions.DateDiff("Hour",DateTime.Now,new DateTime(2018,2,2,8,48,00));//Can only be used in linq to entities.
        }


        /// <summary>
        /// EntityFramework properties modify samples.
        /// </summary>
        private static void PropertyModifiedSample(TodoDbContext ctx, Tag tag, params string[] props)
        {
            UpdateProperty(ctx, tag, props);
        }

        private static void UpdateProperty(TodoDbContext ctx, Tag tag, params string[] props)
        {

            ctx.Tag.Attach(tag);
            if (ctx.Entry(tag).State != EntityState.Modified)
            {
                foreach (var prop in props)
                {
                    ctx.Entry(tag).Property(prop).IsModified = true;
                }
            }
            ctx.SaveChanges();
        }


        /// <summary>
        /// EntityFramework object state manager samples.
        /// </summary>
        /// <param name="ctx"></param>
        private static void StateSample(TodoDbContext ctx)
        {
            ctx.Tag.ToList()
               .ForEach(t => Console.WriteLine(ctx.Entry(t).State));//Unchanged.
            var tag = new Tag() { Name = "散户之佳", Order = 1 };
            Console.WriteLine($"Tag构造之后的状态：{ctx.Entry(tag).State}");//Detached.
            ctx.Tag.Attach(tag);
            Console.WriteLine($"Tag被附加之后的状态：{ctx.Entry(tag).State}");//Unchanged.
            ctx.Tag.Add(tag);
            Console.WriteLine($"Tag插入之后的状态：{ctx.Entry(tag).State}");//Added.
            ctx.SaveChanges();//Save changes and commit insert.
            ctx.Entry(tag).Property(t => t.Name).IsModified = true;
            Console.WriteLine($"Tag某属性被修改的状态：{ctx.Entry(tag).State}");//Modifiedd.
            ctx.SaveChanges(); //Save changes and commit modify.
            tag.Name = "散户之佳大大大大红";
            ctx.Entry(tag).State = EntityState.Modified;
            Console.WriteLine($"Tag被修改的状态：{ctx.Entry(tag).State}");//Modifiedd.
            ctx.SaveChanges(); //Save changes and commit modify.
            ctx.Tag.Remove(tag);
            Console.WriteLine($"Tag被删除时的状态：{ctx.Entry(tag).State}");//Deleted.
            ctx.SaveChanges(); //Save changes and commit delete.
        }


        /// <summary>
        /// List query samples.
        /// </summary>
        /// <param name="ctx"></param>
        private static void ListSample(TodoDbContext ctx)
        {
            //var news = ctx.News.First();
            //Console.WriteLine($@"标题:{news.Title},
            //                  \t分类:{news.Category.Name},\t描述:{news.Description},\t标签:{string.Join("、", news.Tags.Select(t => t.Name))}发帖者:\t{news.User.UserName}");//LazyLoading.
            var list = ctx.News.Join(ctx.Category, n => n.CategoryId, c => c.Id, (n, c) => new { n, c })
                .Join(ctx.User, o => o.n.UserId, u => u.Id, (o, u) => new { o, u })
                .Join(ctx.UserInfo, a => a.u.Id, u => u.Id, (a, u) => new
                {
                    Title = a.o.n.Title,
                    Desc = a.o.n.Description,
                    UserName = a.u.UserName,
                    Age = u.Age,
                    CategoryName = a.o.c.Name
                });
            list.ToList().ForEach(n => Console.WriteLine($@"标题:{n.Title},
                                  \t分类:{n.CategoryName},\t描述:{n.Desc},发帖者:\t{n.UserName}"));//Join.
            var list_ = ctx.Category.GroupJoin(ctx.News, c => c.Id, n => n.CategoryId, (c, n) => new { CatetogryName = c.Name, Items = n });
            list_.ToList()
                .ForEach(i => Console.WriteLine($"分类名称:{i.CatetogryName},新闻:{string.Join(",", i.Items.Select(n => n.Title))}"));

            var list__ = ctx.News.Include("Tags").Include("User").Include("User.UserInfo").Include("Category");
            list__.ToList()
                .ForEach(n => Console.WriteLine($"{n.Title}{string.Join(",", n.Tags.Select(t => t.Name))}{n.User.UserName}{n.Category.Name}{n.User.UserInfo.Age}"));

            var list___ = ctx.News.Include(n => n.User).Include(n => n.Tags).Include(n => n.Category).Include(n => n.User.UserInfo);
            list___.ToList()
                .ForEach(n => Console.WriteLine($"新闻标题:{n.Title},\t标签:{string.Join(",", n.Tags.Select(t => t.Name))},\t发帖用户:{n.User.UserName}\t,分类:{n.Category.Name},\t年龄:{n.User.UserInfo.Age}\t"));
        }


        private static void BulkInsertSample(TodoDbContext ctx)
        {
            IList<User> users = new List<User>();
            for (int i = 0; i < 1000000; i++)
            {
                users.Add(new User() {   UserName="ZhangJian"+i, Pwd=i.ToString()});
            }
            //var myConn = ctx.Database.Connection;
            var myConn = new System.Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["TodoDbContext"].ConnectionString);
            var sw = new Stopwatch();
            sw.Start();
            new Repository.BaseRepository<User>().BulkInsert(myConn,users);
            sw.Stop();
            Console.WriteLine(sw.Elapsed.ToString());
        }
    }
}
